// -*- c-basic-offset: 2 default-tab-width: 2 indent-tabs-mode: t -*-
// vim: autoindent tabstop=2 noexpandtab shiftwidth=2 softtabstop=2
//===------------ Array.h
//
//             This file is part of the reactor project
//                Author: R-Core Team
//
//===---------------------------------------------------------------------===//

#ifndef _ARRAY_H_
#define _ARRAY_H_

#include <string>
#include <iostream>
#include "Any.h"

namespace R {

#define TYPE(__type__)\
	__typeof__(__type__::dataType)

#define array_none
#define array_no_gcroot(a, b)
#define array_no_tracer(a, b)

	// class name - parent name
#define on_number_arrays(__todo__)																		 \
	__todo__(Logical, Number, r_bool,   array_no_gcroot,   array_numbers) \
	__todo__(Int,     Number, r_int,    array_no_gcroot,   array_numbers) \
	__todo__(Double,  Number, r_double, array_no_gcroot,   array_numbers)

	// class name - parent name
#define on_number_and_string_arrays(__todo__)														\
	on_number_arrays(__todo__)                                            \
	on_string_arrays(__todo__)

#define on_string_arrays(__todo__)\
	__todo__(String,  Array,  r_string, array_no_gcroot,   array_string )	\

	// class name - parent name
#define on_arrays(__todo__)																							\
	__todo__(Array,   Any,    uint64_t, array_no_gcroot,   array_parent ) \
	__todo__(Number,  Array,  uint64_t, array_no_gcroot,   array_number ) \
	__todo__(Vector,  Array,  Any*,     llvm_gcroot,       array_vector )	\
	on_number_and_string_arrays(__todo__)

#define all_concrete(t_name, t_parent, t_content, elmt_gc_root)					\
	BASE_RCLASS(t_name);																									\
	public:																																\
																																				\
	static t_content dataType;																						\
																																				\
	t_content content[1];																									\
																																				\
	static t_name* doNew(uint32_t length);																\
	static t_name* doNewSingle(t_content value);													\
																																				\
	t_content getElement(uint32_t i);																			\
	void      setElement(t_content val, uint32_t i);											\
	t_name* enlarge(uint32_t n);																					\
	t_name* shrinkAt(uint32_t n, bool with_attributes = true);						\
	void lightShrinkAt(uint32_t n);	/* no duplication */									\
																																				\
	virtual t_name* newInstance(uint32_t size);														\
	virtual t_name* newInstanceWith(uint32_t size, ...);									\
	virtual Array*  reverse();																						\
	virtual Array*  duplicate(bool with_attributes = false);							\
	virtual void    print();                                              \
	static t_name*  combine(int size, int nbData, Any **data);            \
	virtual Any* subscript(Any* idx, bool with_check = true);							\


	// FIXME: subscript and so on must also be in vector.
	// Means that we have to implement the converters
	// TODO: Floreal: I'm not so sure,
	// we basically need special implentations not just converters.
#define all_concrete_but_vector(t_name, t_parent, t_content, elmt_gc_root) \
	all_concrete(t_name, t_parent, t_content, elmt_gc_root)								\
																																				\
	virtual r_int   toIntOne();																						\
	virtual r_bool  toLogicalOne();																				\
																																				\
	virtual Any* subscriptAssign(Any* idx, Any* val, Any** out_this);			\
	virtual Any* subset(Any *set);																				\
	virtual Any* subsetAssign(Any *set, Any *values);                     \


#define array_parent(t_name, t_parent, t_content, elmt_gc_root)					\
	BASE_ABSTRACT_RCLASS(t_name)																					\
	public:																																\
	uint32_t  length;																											\
																																				\
	virtual t_name* newInstance(uint32_t size) = 0;												\
	virtual t_name* newInstanceWith(uint32_t size, ...) = 0;							\
	Any*     newSingleInstance();																					\
	uint32_t getLength();

#define array_string(t_name, t_parent, t_content, elmt_gc_root)					\
	all_concrete_but_vector(t_name, t_parent, t_content, elmt_gc_root)		\
	int containsString(char* search);
	
#define array_numbers(t_name, t_parent, t_content, elmt_gc_root)				\
	all_concrete_but_vector(t_name, t_parent, t_content, elmt_gc_root)		\
																																				\
	t_content  max();						        																	\
	t_content  min();	         																						\
	virtual t_name*  opposite();																					\
	virtual Logical* neg();																								\

#define array_number(t_name, t_parent, t_content, elmt_gc_root)					\
	BASE_ABSTRACT_RCLASS(t_name)																					\
	public:

#define array_vector(t_name, t_parent, t_content, elmt_gc_root)	\
	all_concrete(t_name, t_parent, t_content, elmt_gc_root)				\
	virtual void    tracer(word_t closure);												\

#define declareArray(t_name, t_parent, t_content, elmt_gc_root, local_decl) \
	class t_name: public t_parent {																				\
		local_decl(t_name, t_parent, t_content, elmt_gc_root)								\
	};
	
	on_arrays(declareArray);

#undef declareArray
#undef array_parent
#undef array_number
#undef array_string
#undef array_vector
#undef array_numbers
#undef all_concrete
#undef all_concrete_but_vector
}

#endif /* ARRAY_H_ */
